package com.lancoo.ccas53.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lancoo.ccas53.entity.*;
import com.lancoo.ccas53.exception.BizException;
import com.lancoo.ccas53.mapper.*;
import com.lancoo.ccas53.pojo.common.PageInfo;
import com.lancoo.ccas53.pojo.constant.ScheduleState;
import com.lancoo.ccas53.pojo.dto.TeachingClassCourseDto;
import com.lancoo.ccas53.pojo.excel.ErrorExcelVo;
import com.lancoo.ccas53.pojo.excel.ExcelRoom;
import com.lancoo.ccas53.pojo.excel.ExcelSiteAllocation;
import com.lancoo.ccas53.pojo.excel.ExcelVenueInformationSettingsVo;
import com.lancoo.ccas53.pojo.response.digitization.BuildingInfo;
import com.lancoo.ccas53.pojo.vo.RoomCollegeTreeVo;
import com.lancoo.ccas53.pojo.vo.RoomTreeVo;
import com.lancoo.ccas53.service.*;
import com.lancoo.ccas53.util.CollComparatorUtil;
import com.lancoo.ccas53.util.MyExcelUtils;
import com.lancoo.ccas53.util.PagingUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.text.Collator;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 教室 服务实现类
 * </p>
 *
 * @author quin.song
 * @since 2024-05-20
 */
@Service
@Slf4j
public class RoomServiceImpl extends ServiceImpl<RoomMapper, Room> implements RoomService {
    @Resource
    private CollComparatorUtil collComparatorUtil;
    @Resource
    @Lazy
    private YunBasicService yunBasicService;
    @Resource
    private CollegeService collegeService;
    @Resource
    private CampusService campusService;
    @Resource
    private RuleWeekDayService ruleWeekDayService;
    @Resource
    private PeriodSchemeService periodSchemeService;
    @Resource
    private TypeMapper typeMapper;
    @Resource
    private TeachingClassWeekService teachingClassWeekService;
    @Resource
    private RoomMapper roomMapper;
    @Resource
    private TypeService typeService;
    @Resource
    private TeachingClassMapper teachingClassMapper;
    @Resource
    private ActiveTeachMapper activeTeachMapper;
    @Resource
    private ActiveTeachService activeTeachService;
    @Resource
    private ScheduleService scheduleService;
    @Resource
    private RuleUsableService ruleUsableService;
    @Resource
    private TaskInfoService taskInfoService;
    @Resource
    private RoomService roomService;
    @Resource
    private CollegeRoomService collegeRoomService;
    @Resource
    private TeachingClassWeekMapper teachingClassWeekMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void syncRoom(Integer taskId, String schoolId) {
        List<BuildingInfo> buildingInfos = yunBasicService.getBaseRoom(schoolId);

        List<Room> rooms = new ArrayList<>();
        if (CollUtil.isEmpty(buildingInfos)) {
            return;
        }
        //学院信息
        List<College> collegeList = collegeService.lambdaQuery().eq(College::getTaskId, taskId).list();

        //校区信息
        List<String> campusNameList = buildingInfos.stream()
                .flatMap(buildingInfo -> buildingInfo.getBuildingFloors().stream())
                .flatMap(baseFloor -> baseFloor.getFloorRooms().stream())
                .map(floorRoom -> floorRoom.getRoomInfo().getCampus())
                .distinct().collect(Collectors.toList());
        Map<String, Integer> campusMap = campusService.syncCampus(taskId, campusNameList)
                .stream().collect(Collectors.toMap(Campus::getCampusName, Campus::getCampusId));


        Map<String, String> college = collegeList
                .stream().collect(Collectors.toMap(College::getBaseCollegeId, College::getCollegeName));
        college.put(schoolId, "全部学院");
        for (BuildingInfo buildingInfo : buildingInfos) {
            for (BuildingInfo.BuildingFloorsDTO baseFloor : buildingInfo.getBuildingFloors()) {
                for (BuildingInfo.BuildingFloorsDTO.FloorRoomsDTO floorRoom : baseFloor.getFloorRooms()) {
                    BuildingInfo.BuildingFloorsDTO.FloorRoomsDTO.RoomInfoDTO baseRoom = floorRoom.getRoomInfo();
                    if (baseRoom.getRoomTypeLevel() != 1 && baseRoom.getRoomTypeLevel() != 2 && baseRoom.getRoomTypeLevel() != 6) {
                        continue;
                    }
                    //只同步可以排课的教室类型
                    rooms.add(new Room()
                            .setTaskId(taskId)
                            .setBaseRoomId(baseRoom.getRoomId())
                            .setRoomName(baseRoom.getRoomName())
                            .setBaseCollegeId(baseRoom.getCollegeId())
                            .setCollegeName(college.get(baseRoom.getCollegeId()))
                            .setBuildingFloor(baseFloor.getBuildFloor())
                            .setBuildingId(buildingInfo.getBuildingInfo().getBuildingId())
                            .setBuildingName(buildingInfo.getBuildingInfo().getBuildingName())
                            .setBaseRoomType(baseRoom.getRoomType())
                            .setRoomNum(baseRoom.getSeatCount().equals(0) ? Integer.MAX_VALUE : baseRoom.getSeatCount())
                            .setCampusId(campusMap.get(baseRoom.getCampus()))
                            .setCampusName(baseRoom.getCampus())
                            .setIsEnable(1)
                    );

                }
            }
        }
        List<Room> oldRoomList = this.lambdaQuery().eq(Room::getTaskId, taskId).list();


        Map<Integer, Room> oldMap = oldRoomList.stream().collect(Collectors.toMap(Room::getBaseRoomId, Function.identity()));
        rooms.forEach(o -> {
            if (oldMap.containsKey(o.getBaseRoomId())) {
                Room oldRoom = oldMap.get(o.getBaseRoomId());
                BeanUtils.copyProperties(oldRoom, o);
                o.setRoomId(oldRoom.getRoomId());
                o.setTaskId(taskId);
                o.setRoomType(oldRoom.getRoomType());
                o.setRoomTypeName(oldRoom.getRoomTypeName());
                o.setIsEnable(oldRoom.getIsEnable());
                o.setRuleSet(oldRoom.getRuleSet());
                o.setConcurrentClass(oldRoom.getConcurrentClass());
                o.setRemark(oldRoom.getRemark());
                o.setBaseSchemeId(oldRoom.getBaseSchemeId());
                o.setBaseSchemeName(oldRoom.getBaseSchemeName());
            }
        });

        roomService.lambdaUpdate().eq(Room::getTaskId, taskId).remove();
        if (CollUtil.isNotEmpty(rooms)) {
            this.saveBatch(rooms);
//            roomMapper.addBatch(rooms);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void syncRoomAdd(Integer taskId, String schoolId) {
        List<BuildingInfo> buildingInfos = yunBasicService.getBaseRoom(schoolId);

        List<Room> rooms = new ArrayList<>();
        if (CollUtil.isEmpty(buildingInfos)) {
            return;
        }
        //学院信息
        List<College> collegeList = collegeService.lambdaQuery().eq(College::getTaskId, taskId).list();

        //校区信息
        List<String> campusNameList = buildingInfos.stream()
                .flatMap(buildingInfo -> buildingInfo.getBuildingFloors().stream())
                .flatMap(baseFloor -> baseFloor.getFloorRooms().stream())
                .map(floorRoom -> floorRoom.getRoomInfo().getCampus())
                .distinct().collect(Collectors.toList());
        Map<String, Integer> campusMap = campusService.syncCampus(taskId, campusNameList)
                .stream().collect(Collectors.toMap(Campus::getCampusName, Campus::getCampusId));


        Map<String, String> college = collegeList
                .stream().collect(Collectors.toMap(College::getBaseCollegeId, College::getCollegeName));
        college.put(schoolId, "全部学院");
        for (BuildingInfo buildingInfo : buildingInfos) {
            for (BuildingInfo.BuildingFloorsDTO baseFloor : buildingInfo.getBuildingFloors()) {
                for (BuildingInfo.BuildingFloorsDTO.FloorRoomsDTO floorRoom : baseFloor.getFloorRooms()) {
                    BuildingInfo.BuildingFloorsDTO.FloorRoomsDTO.RoomInfoDTO baseRoom = floorRoom.getRoomInfo();
                    if (baseRoom.getRoomTypeLevel() != 1 && baseRoom.getRoomTypeLevel() != 2 && baseRoom.getRoomTypeLevel() != 6) {
                        continue;
                    }
                    //只同步可以排课的教室类型
                    rooms.add(new Room()
                            .setTaskId(taskId)
                            .setBaseRoomId(baseRoom.getRoomId())
                            .setRoomName(baseRoom.getRoomName())
                            .setBaseCollegeId(baseRoom.getCollegeId())
                            .setCollegeName(college.get(baseRoom.getCollegeId()))
                            .setBuildingFloor(baseFloor.getBuildFloor())
                            .setBuildingId(buildingInfo.getBuildingInfo().getBuildingId())
                            .setBuildingName(buildingInfo.getBuildingInfo().getBuildingName())
                            .setBaseRoomType(baseRoom.getRoomType())
                            .setRoomNum(baseRoom.getSeatCount().equals(0) ? Integer.MAX_VALUE : baseRoom.getSeatCount())
                            .setCampusId(campusMap.get(baseRoom.getCampus()))
                            .setCampusName(baseRoom.getCampus())
                            .setConcurrentClass(1)
                            .setIsEnable(1)
                    );

                }
            }
        }
        List<Room> oldRoomList = this.lambdaQuery().eq(Room::getTaskId, taskId).list();
        List<Room> addRoom = collComparatorUtil.getAdded(oldRoomList, rooms);

        if (CollUtil.isNotEmpty(addRoom)) {
            roomMapper.addBatch(addRoom);
        }

    }

    @Override
    public PageInfo<Room> getRoomList(Page<Room> page, Integer taskId, Integer campusId, Integer roomType, Integer isEnable) {
        Page<Room> roomPage = roomService.lambdaQuery().eq(Room::getTaskId, taskId)
                .eq(ObjUtil.isNotNull(campusId), Room::getCampusId, campusId)
                .eq(ObjUtil.isNotNull(roomType), Room::getRoomType, roomType)
                .eq(isEnable == 1, Room::getIsEnable, isEnable)
                .page(page);
        return PagingUtil.formatPageResult(roomPage);
    }

    @Override
    public PageInfo<Room> getRoomList1(Page<Room> page, Integer taskId, Integer campusId, Integer roomType, Integer isEnable, Integer ruleSet, String keyword, Integer buildingId) {
        Page<Room> roomPage = roomService.lambdaQuery().eq(Room::getTaskId, taskId)
                .eq(ObjUtil.isNotNull(campusId), Room::getCampusId, campusId)
                .eq(ObjUtil.isNotNull(roomType), Room::getRoomType, roomType)
                .eq(ObjUtil.isNotNull(buildingId), Room::getBuildingId, buildingId)
                .eq(isEnable == 1, Room::getIsEnable, isEnable)
//                .isNull(ruleSet != null && ruleSet == 2, Room::getRoomType)
                .eq(ObjUtil.isNotNull(ruleSet), Room::getRuleSet, ruleSet)
                .like(StrUtil.isNotEmpty(keyword), Room::getRoomName, keyword)
                .page(page);
        return PagingUtil.formatPageResult(roomPage);
    }

    @Override
    public Boolean updateRoom(Integer roomType, String roomTypeName, Integer roomNum, Integer isEnable, Integer concurrentClass, String remark, List<Long> roomIds) {
        this.lambdaUpdate().set(ObjUtil.isNotNull(roomType), Room::getRoomType, roomType)
                .set(ObjUtil.isNotNull(roomTypeName), Room::getRoomTypeName, roomTypeName)
                .set(ObjUtil.isNotNull(roomNum), Room::getRoomNum, roomNum)
                .set(ObjUtil.isNotNull(isEnable), Room::getIsEnable, isEnable)
                .set(remark != null, Room::getRemark, remark)
                .set(ObjUtil.isNotNull(concurrentClass), Room::getConcurrentClass, concurrentClass)
                .in(Room::getRoomId, roomIds)
                .update();
        return true;
    }

    @Override
    public Boolean clearRoom(Integer taskId) {
        roomMapper.updateRoomList(taskId);
        return true;
    }

    @Override
    public List<RoomTreeVo> getRoomTree(Integer taskId, String keyword) {
        List<Room> roomList = this.lambdaQuery().eq(Room::getTaskId, taskId)
                .like(StrUtil.isNotBlank(keyword), Room::getRoomName, keyword).list();
        List<RoomTreeVo> roomTreeVos = new ArrayList<>();
        Map<String, List<Room>> roomMap = roomList.stream().collect(Collectors.groupingBy(Room::getBuildingName,
                () -> new TreeMap<>(Collator.getInstance(Locale.CHINA)), Collectors.toList()));
        for (Map.Entry<String, List<Room>> entry : roomMap.entrySet()) {
            roomTreeVos.add(new RoomTreeVo()
                    .setBuildingName(entry.getKey())
                    .setRooms(entry.getValue()));
        }
        return roomTreeVos;
    }

    @Override
    public List<Room> getBuildingList(Integer taskId, Integer campusId) {
        return roomMapper.getBuildingList(taskId, campusId);
    }

    @Override
    public List<Integer> getBuildingFloor(Integer taskId, Integer campusId, Integer buildingId) {
        return roomMapper.getBuildingFloor(taskId, campusId, buildingId);
    }

    @Override
    public List<Type> getRoomType(Integer taskId, Integer campusId, Integer buildingId, Integer floor) {
//        return roomMapper.getRoomType(taskId, campusId, buildingId,floor);
        return typeService.lambdaQuery().eq(Type::getTaskId, taskId)
                .eq(Type::getTypeMode, 2).eq(Type::getFlag, 2).list();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean getRoomTypeById(Integer typeId) {
        Type type = typeService.getById(typeId);
        if (type == null) {
            return true;
        }
        if (type.getTypeMode() == 1) {
            //清空对应的活动类型
            List<ActiveTeach> list = activeTeachService.lambdaQuery().eq(ActiveTeach::getTypeId, type.getTypeId()).list();
            if (list != null && list.size() != 0) {
                List<Integer> collect = list.stream().map(ActiveTeach::getTypeId).collect(Collectors.toList());
                activeTeachMapper.deleteByTypeId(collect);
            }
        } else if (type.getTypeMode() == 2) {
            roomMapper.updateByType(typeId);
            teachingClassWeekMapper.updateByType(typeId);
//            this.lambdaUpdate().eq(Room::getRoomType,typeId).set(Room::getRoomType,null).set(Room::getRoomTypeName,null).update();
//            teachingClassWeekService.lambdaUpdate().eq(TeachingClassWeek::getRoomType,typeId).set(TeachingClassWeek::getRoomType,null).set(TeachingClassWeek::getRoomTypeName,null).update();
        }
        return typeService.removeById(typeId);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importSiteAllocation(HttpServletResponse response, Integer taskId, Integer flag, MultipartFile file) {

        List<ExcelSiteAllocation> excelTeachingActivities = this.readSiteAllocation(file);

        if (flag == 2) {
            collegeService.lambdaUpdate().eq(College::getTaskId, taskId).set(College::getRoomSet, 0).update();
            collegeRoomService.lambdaUpdate().eq(CollegeRoom::getTaskId, taskId).remove();
        }


        Map<String, Room> roomMap = roomMapper.selectList(new LambdaQueryWrapper<Room>().eq(Room::getTaskId, taskId)).stream()
                .collect(Collectors.toMap(Room::getRoomName, Function.identity(), (o1, o2) -> o1));

        Map<String, College> collegeMap = collegeService.lambdaQuery().eq(College::getTaskId, taskId).list().stream()
                .collect(Collectors.toMap(College::getCollegeName, Function.identity(), (o1, o2) -> o1));


        Map<Integer, Campus> campusMap = campusService.lambdaQuery().eq(Campus::getTaskId, taskId).list().stream().collect(Collectors.toMap(Campus::getCampusId, Function.identity(), (o1, o2) -> o1));


        Long index = 3L;
        for (ExcelSiteAllocation excelTeachingActivity : excelTeachingActivities) {
            excelTeachingActivity.setId(index);
            index++;
        }


        List<ErrorExcelVo> errorExcelVos = new ArrayList<>();
        for (ExcelSiteAllocation excelTeachingActivity : excelTeachingActivities) {

            if (StringUtils.isBlank(excelTeachingActivity.getCollegeName()) || !collegeMap.containsKey(excelTeachingActivity.getCollegeName().trim())) {
                ErrorExcelVo errorExcelVo = new ErrorExcelVo();
                errorExcelVo.setErrorIndex(excelTeachingActivity.getId());
                errorExcelVo.setErrorMsg(excelTeachingActivity.getCollegeName() + "开课单位本计划未设置");
                errorExcelVos.add(errorExcelVo);
            }


            if (StringUtils.isBlank(excelTeachingActivity.getRoom().trim())) {
                continue;
            } else {
                List<String> room = new ArrayList<>(Arrays.asList(excelTeachingActivity.getRoom().split(",")));

                room.forEach(o -> {
                    if (!roomMap.containsKey(o)) {
                        ErrorExcelVo errorExcelVo = new ErrorExcelVo();
                        errorExcelVo.setErrorIndex(excelTeachingActivity.getId());
                        errorExcelVo.setErrorMsg(excelTeachingActivity.getRoom() + o + "场地不存在");
                        errorExcelVos.add(errorExcelVo);
                    }
                });
            }


        }


        Integer errorExcelVos1 = errorExcelVos.size();
        if (CollUtil.isNotEmpty(errorExcelVos)) {
            String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy_MM_dd_HH_mm_ss"));
            response.setCharacterEncoding("UTF-8");
            response.setHeader("content-Type", "application/vnd.ms-excel; charset=utf-8");

            MyExcelUtils.exportExcel(errorExcelVos,
                    "导入场地分配信息错误",
                    "错误信息",
                    ErrorExcelVo.class,
                    "导入错误信息" + time + ".xls", response);

            throw new BizException("导入场地分配信息错误");
        }

        if (errorExcelVos1 == 0) {
            List<ErrorExcelVo> errorExcelVos2 = new ArrayList<>();


            List<College> colleges = new ArrayList<>();
            List<CollegeRoom> collegeRooms = new ArrayList<>();

            for (ExcelSiteAllocation excelTeachingActivity : excelTeachingActivities) {

                if (StringUtils.isBlank(excelTeachingActivity.getRoom())) {
                    continue;
                }

                List<String> roomName = new ArrayList<>(Arrays.asList(excelTeachingActivity.getRoom().split(",")));

                College college = collegeMap.get(excelTeachingActivity.getCollegeName());

                List<Long> roomIds = collegeRoomService.lambdaQuery().eq(CollegeRoom::getTaskId, taskId).eq(CollegeRoom::getBaseCollegeId, college.getBaseCollegeId())
                        .list().stream().map(CollegeRoom::getRoomId).collect(Collectors.toList());

                roomName.forEach(o -> {
                    Room room = roomMap.get(o);

                    if (!roomIds.contains(room.getRoomId())) {
                        CollegeRoom collegeRoom = new CollegeRoom();
                        collegeRoom.setTaskId(taskId);

                        collegeRoom.setBaseCollegeId(college.getBaseCollegeId());
                        collegeRoom.setRoomId(room.getRoomId());
                        collegeRoom.setRoomName(room.getRoomName());
                        collegeRoom.setBuildingName(room.getBuildingName());

                        collegeRoom.setCampusId(campusMap.get(room.getCampusId()).getCampusId());
                        collegeRoom.setCampusName(campusMap.get(room.getCampusId()).getCampusName());

                        collegeRooms.add(collegeRoom);
                    }
                });

                college.setRoomSet(1);
                colleges.add(college);
            }

            Integer errorExcelVos3 = errorExcelVos2.size();

            if (CollUtil.isNotEmpty(errorExcelVos2)) {
                String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy_MM_dd_HH_mm_ss"));
                response.setCharacterEncoding("UTF-8");
                response.setHeader("content-Type", "application/vnd.ms-excel; charset=utf-8");

                MyExcelUtils.exportExcel(errorExcelVos2,
                        "导入场地分配信息错误",
                        "错误信息",
                        ErrorExcelVo.class,
                        "导入场地分配信息错误" + time + ".xls", response);
                throw new BizException("导入场地分配信息错误");
            }

            if (errorExcelVos3 == 0) {
                if (CollUtil.isNotEmpty(collegeRooms)) {

                    collegeRoomService.saveOrUpdateBatch(collegeRooms);
                }

                if (CollUtil.isNotEmpty(colleges)) {
                    collegeService.saveOrUpdateBatch(colleges);
                }
            }
        }
    }

    @Override
    public List<Long> getCurrentRoom(Integer taskId) {
        return baseMapper.getCurrentRoom(taskId);
    }


    @Override
    public List<Room> getBuildingListV2(Integer taskId) {
        return roomMapper.getBuildingListV2(taskId);
    }

    @Override
    public Boolean updateRoomPeriod(String baseSchemeId, String baseSchemeName, List<Room> roomIds, Integer taskId) {
        this.lambdaUpdate().set(Room::getBaseSchemeId, baseSchemeId)
                .set(Room::getBaseSchemeName, baseSchemeName)
                .set(Room::getRuleSet, 1)
                .in(Room::getRoomId, roomIds.stream().map(Room::getRoomId).collect(Collectors.toList())).update();
        return true;
    }

    private List<ExcelSiteAllocation> readSiteAllocation(MultipartFile file) {
        List<ExcelSiteAllocation> excelTeachingActivities = new ArrayList<>();
        List<String> expectedHeaders = Arrays.asList(
                "开课单位", "分配场地", "分配状态");
        try {

            InputStream inputStream = file.getResource().getInputStream();
            ExcelReader reader = ExcelUtil.getReader(inputStream, 0);
            //读取表头 判断是否符合预期
            List<String> actualHeaders = reader.readRow(1).stream()
                    .map(Object::toString).filter(org.apache.commons.lang3.StringUtils::isNotBlank)
                    .collect(Collectors.toList());
            if (!expectedHeaders.equals(actualHeaders)) {
                throw new BizException(5, "导入模板不匹配，请按照标准模板编辑后导入");
            }

            reader.addHeaderAlias("开课单位", "collegeName");
            reader.addHeaderAlias("分配场地", "room");
            reader.addHeaderAlias("分配状态", "flag");

            excelTeachingActivities = reader.read(1, 2, ExcelSiteAllocation.class);
            reader.close();
        } catch (Exception ex) {
            log.info("excel导入教学任务失败:{}", ex.getMessage());
        }

        if (excelTeachingActivities.size() == 0) {
            throw new BizException(5, "导入数据为空，请检查后重新导入");
        }

        return excelTeachingActivities;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void importVenueInformationSettings(HttpServletResponse response, Integer taskId, Integer flag, MultipartFile file) {

        List<ExcelVenueInformationSettingsVo> excelTeachingActivities = this.readVenueInformationSettings(file);

        if (flag == 2) {
            this.lambdaUpdate().in(Room::getTaskId, taskId).set(Room::getRoomType, null).set(Room::getRoomTypeName, null)
                    .set(Room::getRoomNum, 0).set(Room::getIsEnable, 0).set(Room::getConcurrentClass, 0).update();
        }


        Map<String, List<Room>> roomMap = roomMapper.selectList(new LambdaQueryWrapper<Room>().eq(Room::getTaskId, taskId)).stream()
                .collect(Collectors.groupingBy(Room::getRoomName));


        List<Type> typeList = typeService.lambdaQuery().eq(Type::getTaskId, taskId).eq(Type::getTypeMode, 2).list();


        List<String> roomTypeName = typeList.stream().map(Type::getTypeName).collect(Collectors.toList());

        Map<String, String> periodSchemeMap = periodSchemeService.lambdaQuery().eq(PeriodScheme::getTaskId, taskId).list().stream()
                .collect(Collectors.toMap(PeriodScheme::getBaseSchemeName, PeriodScheme::getBaseSchemeId, (o1, o2) -> o1));


        List<String> roomType = excelTeachingActivities.stream().filter(p -> org.apache.commons.lang3.StringUtils.isNotBlank(p.getRoomType())).map(ExcelVenueInformationSettingsVo::getRoomType).map(String::trim).distinct().collect(Collectors.toList());

        List<Type> roomTypes = new ArrayList<>();

        roomType.forEach(o -> {

            if (!roomTypeName.contains(o)) {
                Type roomType1 = new Type();
                roomType1.setTaskId(taskId);
                roomType1.setTypeMode(2);
                roomType1.setTypeName(o);
                roomTypes.add(roomType1);
            }
        });


        if (CollUtil.isNotEmpty(roomTypes)) {
            typeService.saveBatch(roomTypes);
        }

        Map<String, Integer> typeMap = typeService.lambdaQuery().eq(Type::getTaskId, taskId).list().stream()
                .collect(Collectors.toMap(Type::getTypeName, Type::getTypeId));


        Long index = 3L;
        for (ExcelVenueInformationSettingsVo excelTeachingActivity : excelTeachingActivities) {
            excelTeachingActivity.setId(index);
            index++;
        }


        List<ErrorExcelVo> errorExcelVos = new ArrayList<>();
        for (ExcelVenueInformationSettingsVo excelTeachingActivity : excelTeachingActivities) {

            if (StringUtils.isBlank(excelTeachingActivity.getRoomName()) || !roomMap.containsKey(excelTeachingActivity.getRoomName().trim())) {
                ErrorExcelVo errorExcelVo = new ErrorExcelVo();
                errorExcelVo.setErrorIndex(excelTeachingActivity.getId());
                errorExcelVo.setErrorMsg(excelTeachingActivity.getRoomName() + "本教学任务不存在");
                errorExcelVos.add(errorExcelVo);
            }

            if (StringUtils.isNotBlank(excelTeachingActivity.getPeriodScheme()) && !periodSchemeMap.containsKey(excelTeachingActivity.getPeriodScheme().trim())) {
                ErrorExcelVo errorExcelVo = new ErrorExcelVo();
                errorExcelVo.setErrorIndex(excelTeachingActivity.getId());
                errorExcelVo.setErrorMsg(excelTeachingActivity.getRoomName() + "本计划课时方案不存在");
                errorExcelVos.add(errorExcelVo);
            }


        }


        Integer errorExcelVos1 = errorExcelVos.size();
        if (CollUtil.isNotEmpty(errorExcelVos)) {
            String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy_MM_dd_HH_mm_ss"));
            response.setCharacterEncoding("UTF-8");
            response.setHeader("content-Type", "application/vnd.ms-excel; charset=utf-8");

            MyExcelUtils.exportExcel(errorExcelVos,
                    "导入场地信息信息错误",
                    "错误信息",
                    ErrorExcelVo.class,
                    "导入场地信息错误信息" + time + ".xls", response);
            throw new BizException("导入场地信息错误信息");
        }

        if (errorExcelVos1 == 0) {

            List<Room> rooms = new ArrayList<>();

            for (ExcelVenueInformationSettingsVo excelTeachingActivity : excelTeachingActivities) {

                Room room = roomMap.get(excelTeachingActivity.getRoomName().trim()).get(0);

                if (ObjUtil.isNotNull(room)) {
                    room.setRoomType(StringUtils.isNotBlank(excelTeachingActivity.getRoomType().trim()) ? typeMap.get(excelTeachingActivity.getRoomType()) : null);
                    room.setRoomTypeName(StringUtils.isNotBlank(excelTeachingActivity.getRoomType().trim()) ? excelTeachingActivity.getRoomType() : "");
                    room.setRoomNum(excelTeachingActivity.getRoomNum());

                    if (StringUtils.isNotBlank(excelTeachingActivity.getPeriodScheme().trim())) {
                        room.setBaseSchemeId(periodSchemeMap.get(excelTeachingActivity.getPeriodScheme().trim()));
                        room.setBaseSchemeName(excelTeachingActivity.getPeriodScheme().trim());
                    }
                    room.setIsEnable("已启用".equals(excelTeachingActivity.getIsEnable()) ? 1 : 0);
                    room.setConcurrentClass(excelTeachingActivity.getClassNum());
                    room.setRemark(excelTeachingActivity.getRemark());
                    rooms.add(room);
                }
            }


            if (CollUtil.isNotEmpty(rooms)) {
                this.saveOrUpdateBatch(rooms);
            }
        }


    }


    private List<ExcelVenueInformationSettingsVo> readVenueInformationSettings(MultipartFile file) {
        List<ExcelVenueInformationSettingsVo> excelTeachingActivities = new ArrayList<>();
        List<String> expectedHeaders = Arrays.asList(
                "教室名称", "楼宇/场馆", "校区名称", "课时方案", "场地类型", "场地容量", "同时上课班级数", "备注", "操作");
        try {

            InputStream inputStream = file.getResource().getInputStream();
            ExcelReader reader = ExcelUtil.getReader(inputStream, 0);
            //读取表头 判断是否符合预期
            List<String> actualHeaders = reader.readRow(1).stream()
                    .map(Object::toString).filter(org.apache.commons.lang3.StringUtils::isNotBlank)
                    .collect(Collectors.toList());
            if (!expectedHeaders.equals(actualHeaders)) {
                throw new BizException(5, "导入模板不匹配，请按照标准模板编辑后导入");
            }

            reader.addHeaderAlias("教室名称", "roomName");
            reader.addHeaderAlias("楼宇/场馆", "buildingFloor");
            reader.addHeaderAlias("校区名称", "campusName");
            reader.addHeaderAlias("课时方案", "periodScheme");
            reader.addHeaderAlias("备注", "remark");
            reader.addHeaderAlias("场地类型", "roomType");
            reader.addHeaderAlias("场地容量", "roomNum");
            reader.addHeaderAlias("同时上课班级数", "classNum");
            reader.addHeaderAlias("操作", "isEnable");

            excelTeachingActivities = reader.read(1, 2, ExcelVenueInformationSettingsVo.class);
            reader.close();
        } catch (Exception ex) {
            log.info("excel导入教学任务失败:{}", ex.getMessage());
        }

        if (excelTeachingActivities.size() == 0) {
            throw new BizException(5, "导入数据为空，请检查后重新导入");
        }

        return excelTeachingActivities;


    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void exportHolidaySchedule(HttpServletResponse response, Integer taskId, Integer campusId, Integer roomType, Integer isEnable, Integer currentPage, Integer pageSize) {


        List<ExcelRoom> excelRooms = new ArrayList<>();

        Page<Room> page = new Page<>(1, -1);


        TaskInfo taskInfo = taskInfoService.getById(taskId);


        List<Campus> campuses = campusService.lambdaQuery().eq(Campus::getTaskId, taskId).list();

        Campus campus = new Campus();

        List<Type> typeList = typeService.lambdaQuery().eq(Type::getTaskId, taskId).eq(Type::getTypeMode, 2).list();

        if (CollUtil.isNotEmpty(campuses) && ObjUtil.isNotNull(campusId)) {

            List<Campus> campusList = campuses.stream().filter(p -> p.getCampusId().equals(campusId)).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(campusList)) {
                campus = campusList.get(0);
            }
        }
        Type type = new Type();
        if (CollUtil.isNotEmpty(typeList) && ObjUtil.isNotNull(roomType)) {
            List<Type> types = typeList.stream().filter(p -> p.getTypeId().equals(roomType)).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(types)) {
                type = types.get(0);
            }
        }


        //构建标题
        String title = " {} {}节假日安排导出" + "\n" + "校区:{}" + "\n" + "场地类型:{}";
        String format = StrUtil.format(title, taskInfo.getTermName(), taskInfo.getSchoolName()
                , ObjUtil.isNull(campusId) ? "全部校区" : campus.getCampusName(), ObjUtil.isNull(roomType) ? "全部类型" : type.getTypeName());


        PageInfo<Room> roomList = this.getRoomList(page, taskId, campusId, roomType, isEnable);

        List<Room> rooms = roomList.getList();


        rooms.forEach(o -> {
            ExcelRoom excelRoom = new ExcelRoom();
            excelRoom.setRoomName(o.getRoomName());
            excelRoom.setBuildingFloorName(o.getBuildingName());
            excelRoom.setCampusName(o.getCampusName());
            excelRoom.setPeriodScheme(o.getBaseSchemeName());
            excelRoom.setReserve(o.getRemark());
            excelRoom.setRoomTypeName(o.getRoomTypeName());
            excelRoom.setClassNum(o.getConcurrentClass());
            excelRoom.setIsEnable(o.getIsEnable() == 1 ? "已启用" : "未启用");
            excelRoom.setRoomNum(o.getRoomNum());
            excelRooms.add(excelRoom);
        });


        String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy_MM_dd_HH_mm_ss"));

        response.setCharacterEncoding("UTF-8");
        response.setHeader("content-Type", "application/vnd.ms-excel; charset=utf-8");

        MyExcelUtils.exportExcel(excelRooms,
                format,
                "教学活动安排",
                ExcelRoom.class,
                "校区场地信息设置" + time + ".xls", response);

    }

    @Override
    public List<RoomCollegeTreeVo> getRoomCollegeTree(Integer taskId, String schoolId, String term, String baseCollegeId, Integer module, String keyword) {
        List<Room> roomList = roomMapper.getCollegeRoom(taskId, baseCollegeId, keyword);
        Page<TeachingClassCourseDto> page = new Page<>(1, -1);
        List<TeachingClassCourseDto> records = teachingClassMapper.getCourseTeachingClassForArrange(page, taskId, null).getRecords();

        List<Schedule> schedules = scheduleService.lambdaQuery()
                .eq(Schedule::getTaskId, taskId)
                .list();
        List<Long> allRoomIds = schedules.stream().map(Schedule::getRoomId).collect(Collectors.toList());
        roomList = roomList.stream().filter(o -> allRoomIds.contains(o.getRoomId())).collect(Collectors.toList());

        if (module == 1) {
            List<TeachingClassCourseDto> unRange = records.stream()
                    .filter(o -> o.getState() != ScheduleState.NORMAL.getCode())
                    .collect(Collectors.toList());
            RuleUsable ruleUsable = ruleUsableService.lambdaQuery()
                    .eq(RuleUsable::getTaskId, taskId)
                    .eq(RuleUsable::getCode, 6)
                    .one();
            if (ruleUsable == null) {
                throw new BizException("管理员未设置排课规则");
            }
            String rule = ruleUsable.typeToStrong();
            if (StrUtil.isNotEmpty(baseCollegeId)) {
                unRange = unRange.stream().filter(o -> o.getBaseCollegeId().equals(baseCollegeId) &&
                        ((rule.charAt(0) == '0' && o.getMajorProp() == 2 && o.getStudyNature() == 1)
                                || (rule.charAt(1) == '0' && o.getMajorProp() == 2 && o.getStudyNature() == 2)
                                || (rule.charAt(2) == '0' && o.getMajorProp() == 1 && o.getStudyNature() == 1)
                                || (rule.charAt(3) == '0' && o.getMajorProp() == 1 && o.getStudyNature() == 2))
                ).collect(Collectors.toList());
            }
//            } else {
//                unRange = unRange.stream().filter(o ->
//                        (rule.charAt(0) == '1' && o.getMajorProp() == 2 && o.getStudyNature() == 1)
//                                || (rule.charAt(1) == '1' && o.getMajorProp() == 2 && o.getStudyNature() == 2)
//                                || (rule.charAt(2) == '1' && o.getMajorProp() == 1 && o.getStudyNature() == 1)
//                                || (rule.charAt(3) == '1' && o.getMajorProp() == 1 && o.getStudyNature() == 2)
//                ).collect(Collectors.toList());
//            }
            if (CollUtil.isNotEmpty(unRange)) {
                List<Long> roomIds = unRange.stream().map(TeachingClassCourseDto::getRoomId).collect(Collectors.toList());

                roomList.forEach(o -> {
                    if (roomIds.contains(o.getRoomId())) {
                        o.setScheduleState(false);
                    }
                });
            }
        }
        return Room.toRoomTree(roomList);
    }

    @Override
    public List<Room> getRoomListByBuilding(Integer taskId, Integer campusId, Integer buildingId) {
        return roomMapper.getRoomListByBuilding(taskId, campusId, buildingId);
    }
}
